package org.wzl.databasesync.service.impl;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.wzl.databasesync.dto.DatabaseInfo;
import org.wzl.databasesync.dto.FiledDesc;
import org.wzl.databasesync.dto.TableDesc;
import org.wzl.databasesync.enumerate.SqlGen;
import org.wzl.databasesync.service.SqlGenService;
import org.wzl.databasesync.utils.JdbcUtils;

import java.util.ArrayList;
import java.util.List;

@Slf4j
@Service
public class SqlGenServiceImpl implements SqlGenService {
    @Override
    public List<TableDesc> getAllTables(DatabaseInfo databaseInfo) throws Exception{
        try {
            return JdbcUtils.executeQuery(databaseInfo, String.format(SqlGen.GET_TABLES.getSql()))
                    .stream().map(table -> getTableDesc(databaseInfo, table)).toList();
        } catch (Exception e) {
            log.error("获取数据库表失败", e);
            throw e;
        }
    }

    @Override
    public TableDesc getTableDesc(DatabaseInfo databaseInfo, String tableName) {
        try {
            List<FiledDesc> descList = JdbcUtils.executeQuery(databaseInfo, String.format(SqlGen.TABLE_DESC.getSql(), tableName))
                    .stream()
                    .map(str -> {
                        String[] split = str.split("\t");
                        FiledDesc filedDesc = new FiledDesc();
                        filedDesc.setField(split[0]);
                        filedDesc.setType(split[1]);
                        filedDesc.setNullable(!split[2].equals("NO"));
                        return filedDesc;
                    }).toList();
            return new TableDesc(tableName, descList);
        } catch (Exception e) {
            return null;
        }
    }

    @Override
    public String createTableSql(TableDesc addTable) {
        return "CREATE TABLE " + addTable.getTableName() + " (\n" +
                addTable.getFiledDescList().stream()
                        .map(filedDesc -> filedDesc.getField() + " " + filedDesc.getType())
                        .reduce((a, b) -> a + ",\n" + b).orElse("") +
                "\n);";
    }

    @Override
    public String dropTableSql(TableDesc deleteTable) {
        return "DROP TABLE " + deleteTable.getTableName() + ";";
    }

    @Override
    public String alterTableSql(DatabaseSyncServiceImpl.UpdateTable updateTable) {
        StringBuilder sqlBuilder = new StringBuilder();
        String tableName = updateTable.getTableName();

        List<FiledDesc> addColumns = updateTable.getAddColumns();
        List<FiledDesc> deleteColumns = updateTable.getDeleteColumns();

        if ((addColumns == null || addColumns.isEmpty()) && (deleteColumns == null || deleteColumns.isEmpty())) {
            return ""; // 没有需要修改的列
        }

        sqlBuilder.append("ALTER TABLE `").append(tableName).append("` ");

        List<String> alterStatements = new ArrayList<>();

        // 构造添加字段语句
        if (addColumns != null) {
            for (FiledDesc column : addColumns) {
                StringBuilder colDef = new StringBuilder();
                colDef.append("ADD COLUMN `").append(column.getField()).append("` ")
                        .append(column.getType());

                if (Boolean.FALSE.equals(column.getNullable())) {
                    colDef.append(" NOT NULL");
                } else {
                    colDef.append(" NULL");
                }

                if (column.getDefaultValue() != null && !column.getDefaultValue().isEmpty()) {
                    colDef.append(" DEFAULT '").append(column.getDefaultValue()).append("'");
                }

                if (column.getExtra() != null && !column.getExtra().isEmpty()) {
                    colDef.append(" ").append(column.getExtra());
                }

                alterStatements.add(colDef.toString());
            }
        }

        // 构造删除字段语句
        if (deleteColumns != null) {
            for (FiledDesc column : deleteColumns) {
                alterStatements.add("DROP COLUMN `" + column.getField() + "`");
            }
        }

        sqlBuilder.append(String.join(", ", alterStatements));
        sqlBuilder.append(";");

        return sqlBuilder.toString();
    }
}
